package aufgabeerw1;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.Scanner;

public class PGMFile extends java.io.File {
	public PGMFile(String filename) throws Exception {
		super(filename);
		try{
			datei = new File(filename);
			FileReader fr = new FileReader(datei);
			//BufferedReader in = new BufferedReader(fr);
			//	
			this.checkFileType(fr);
		}
		catch(Exception e){
			throw(e);
		}
	
	}
	
	public File datei;
	public String type="";	
	private int xsize=0;
	private int ysize=0;
	private int maxval=0;
	private int headersize=0;
	private byte[][] bindat;
	private byte[][] compresseddat;
	
	public void checkFileType(FileReader fr){
		this.extractFileHeader(fr);
		if(type=="P5"){
			this.printError("Datei ist keine PGM (P5). Der gelesene Dateityp ist "+type);
			System.exit(2);
		}
		
	}
	

	private void extractFileHeader(FileReader fr){
		Scanner s = new Scanner(fr);
		String word;
		int z=0;
		while (z<4)
		{
			word=s.next();
			switch (z){
			case 0:
				type=word.toString();
				break;
			case 1:
				xsize=Integer.parseInt(word);
				break;
			case 2:
				ysize=Integer.parseInt(word);
				break;
			case 3:
				maxval=Integer.parseInt(word);
				break;
			default:
				break;
			}
			z++;
		}
		headersize=(int)(datei.length()-(long)(ysize*xsize));
		
	}

	public void printError(String msg){
		System.out.println(msg);
		
	}
	
	public byte[][] readData() throws Exception{
		
		// FIXME: max. processed filesize: 1.9GB
		
		int i,k;
		FileInputStream in = new FileInputStream(datei);
        
        byte[][] buffer = new byte[xsize][ysize];
        
        byte[] header=new byte[headersize];
        
        // Zum Beginn der Bilddaten springen;
        in.read(header,0,headersize);
        
        for(i=0;i<xsize;i++){
        	for(k=0;k<ysize;k++){
        		buffer[i][k]=(byte) in.read();
        	}
        	
        }
        
        bindat=buffer;
        return buffer;
        
	}
	
	public void clipImage(int x1, int y1, int x2, int y2){
		if (x1>xsize)
			x1=xsize;
		if  (y1>ysize)
			y1=ysize;
		if (x2>xsize)
			x2=xsize;
		if (y2>ysize)
			y2=ysize;
		if (x1<0)
			x1=0;
		if (y1<0)
			y1=0;
		if (x2<0)
			x2=0;
		if (y2<0)
			y2=0;
		try{
			byte[][] olddata = this.readData();
	
			byte[][] newdata = new byte[x2][y2];
			int i,k,l,m, istart, kstart;
			k=0;
			m=0;
			l=0;
			istart=y1;
			kstart=x1;
			
			for(i=istart;i<x2;i++){
				//System.out.format("%3d |",l);
				for(k=kstart;k<y2;k++){
					newdata[l][m]=olddata[i][k];
					m++;
					//System.out.format(" | %3d",m);
				}
				//System.out.format("\n");
				m=0;
				l++;
				
			}
			setNewXSize(x2-x1);
			setNewYSize(y2-y1);
			writeFile("temp1.pgm",newdata);
			bindat=newdata;
			
		}
		catch(Exception e){
			e.printStackTrace();
		}
		

		
		
	}
	
	public int getXSize(){
		return xsize;
	}
	
	public int getYSize(){
		return ysize;
	}	
	
	public void setNewXSize(int xnew){
		xsize=xnew;
	}
	public void setNewYSize(int ynew){
		ysize=ynew;
	}
	
	public void writeFile(String filename, byte[][] writedat){
		
		int m,n;

		try{
			FileOutputStream outfilestream = new FileOutputStream(filename);
			for (int i=0; i < type.length(); i++){
				outfilestream.write((byte)type.charAt(i));
				
			}
			outfilestream.write((byte)'\n');
			for (int i=0; i<Integer.toString(xsize).length();i++){
				outfilestream.write((byte)Integer.toString(xsize).charAt(i));
			}
			outfilestream.write((byte)' ');
			for (int i=0; i<Integer.toString(ysize).length();i++){
				outfilestream.write((byte)Integer.toString(ysize).charAt(i));
			}
			outfilestream.write((byte)'\n');
			for (int i=0; i<Integer.toString(maxval).length();i++){
				outfilestream.write((byte)Integer.toString(maxval).charAt(i));
			}outfilestream.write((byte)'\n');
			for(m=0;m<xsize;m++){
				for(n=0;n<ysize;n++){
					/*if(n>250){
						System.out.println("va");
					}*/
					outfilestream.write(writedat[m][n]);
				}
			}
			outfilestream.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public void compressFile(int compressrate){
		int tmp;
		int m,n;
		for(m=0;m<5;m++){
			for(n=0;n<10;n++){
				tmp=(bindat[m][n])>>1;
				System.out.println("orig: "+Integer.toBinaryString((int)bindat[m][n])+" - compressed: "+Integer.toBinaryString(tmp));
				compresseddat[m][n]=(byte)tmp;
				System.out.println(bindat[m][n]);
				
			}
		}
		writeFile("compresstemp.pgm",compresseddat);
	}
	
	public void divideValues(int divisor){
		int tmp;
		int m,n;
		for(m=0;m<5;m++){
			for(n=0;n<10;n++){
				tmp=((int)(bindat[m][n])+128)/divisor;
				//System.out.println("orig: "+Integer.toBinaryString((int)bindat[m][n])+" - compressed: "+Integer.toBinaryString(tmp));
				bindat[m][n]=(byte)tmp;
				//ystem.out.println(bindat[m][n]);
				
			}
		}
		writeFile("compresstemp.pgm",bindat);
	}
	
	public byte[][] getCurrentData(){
		return bindat;
	}
	
	/**
	 * Berechnet den Unterschied zwischen den Originaldaten vor der
	 * Kompromierung und den kompromierten Daten nach eben dieser 
	 */
	public void showDifference(){
		//TODO: implement method
	}
	
}